﻿#include "Lua.h"
#include<Windows.h>
QMutex Lua::instanceMutex;
Lua* Lua::instance=nullptr;
Lua::Deleter Lua::deleter(Lua::instanceMutex);
Lua::Lua()
{
    guns<<QStringLiteral("无")<<"AK47"<<"LR300"<<"MP5A4"<<"THOMPSON"<<"SMG"<<"HMLMG"<<"M249"<<"SAR"<<"M39"<<"P250"<<"M92"<<"PROTOTYPE17"<<"PYTHON"<<"REVOLVER";
    L = luaL_newstate();
    luaL_openlibs(L);
    lua_register(L,"IsMouseButtonPressed",IsMouseButtonPressed);
    lua_register(L,"GetRunningTime",GetRunningTime);
    lua_register(L,"MoveMouseRelative",MoveMouseRelative);
    lua_register(L,"IsModifierPressed",IsModifierPressed);
    lua_register(L,"PressKey",PressKey);
    lua_register(L,"ReleaseKey",ReleaseKey);
    lua_register(L,"GetMousePosition",GetMousePosition);
    lua_register(L,"MoveMouseTo",MoveMouseTo);
    lua_register(L,"PressAndReleaseMouseButton",PressAndReleaseMouseButton);
}

void Lua::getsetting()
{
    lua_getglobal(L,"SENSITIVITY");
    float sens=lua_tonumber(L,-1);
    lua_pop(L,1);
    lua_getglobal(L,"ADS_SENSITIVITY");
    float ads_sens=lua_tonumber(L,-1);
    lua_pop(L,1);
    lua_getglobal(L,"FOV");
    int fov=lua_tonumber(L,-1);
    lua_pop(L,1);
    emit send_sens(sens);
    emit send_ads_sens(ads_sens);
    emit send_fov(fov);
}

void Lua::getguns()
{
    emit send_cbb_1(0);
    emit send_cbb_2(0);
    emit send_cbb_3(0);
    emit send_cbb_4(0);
    emit send_cbb_5(0);
    emit send_cbb_6(0);
    for(int i=1;i<15;i++)
    {
        lua_getglobal(L,guns[i].toStdString().c_str());
        int gunindex=lua_tonumber(L,-1);
        lua_pop(L,1);
        if(gunindex==1)
            emit send_cbb_1(i);
        else if(gunindex==2)
            emit send_cbb_2(i);
        else if(gunindex==3)
            emit send_cbb_3(i);
        else if(gunindex==4)
            emit send_cbb_4(i);
        else if(gunindex==5)
            emit send_cbb_5(i);
        else if(gunindex==6)
            emit send_cbb_6(i);
    }
}

void Lua::set_sens(double sens)
{
    lua_pushnumber(L,sens);
    lua_setglobal(L,"SENSITIVITY");
    lua_getglobal(L,"update");
    lua_pcall(L,0,0,0);
}

void Lua::set_ads_sens(double ads_sens)
{
    lua_pushnumber(L,ads_sens);
    lua_setglobal(L,"ADS_SENSITIVITY");
    lua_getglobal(L,"update");
    lua_pcall(L,0,0,0);
}

void Lua::set_fov(int fov)
{
    lua_pushnumber(L,fov);
    lua_setglobal(L,"FOV");
    lua_getglobal(L,"update");
    lua_pcall(L,0,0,0);
}

void Lua::setcbb(int index1, int index2, int index3, int index4, int index5,int index6)
{
    for(int i=1;i<15;i++)
    {
        lua_pushnil(L);
        lua_setglobal(L,guns[i].toStdString().c_str());
    }
    if(index1!=0)
    {
        lua_pushnumber(L,1);
        lua_setglobal(L,guns[index1].toStdString().c_str());
    }
    if(index2!=0)
    {
        lua_pushnumber(L,2);
        lua_setglobal(L,guns[index2].toStdString().c_str());
    }
    if(index3!=0)
    {
        lua_pushnumber(L,3);
        lua_setglobal(L,guns[index3].toStdString().c_str());
    }
    if(index4!=0)
    {
        lua_pushnumber(L,4);
        lua_setglobal(L,guns[index4].toStdString().c_str());
    }
    if(index5!=0)
    {
        lua_pushnumber(L,5);
        lua_setglobal(L,guns[index5].toStdString().c_str());
    }
    if(index6!=0)
    {
        lua_pushnumber(L,6);
        lua_setglobal(L,guns[index6].toStdString().c_str());
    }

    lua_getglobal(L,"update");
    lua_pcall(L,0,0,0);
}

void Lua::getguninfo()
{
    lua_getglobal(L,"kickback");
    bool ison=lua_toboolean(L,-1);
    lua_pop(L,1);
    if(ison)
    {
        lua_getglobal(L,"gun");
        int index=lua_tonumber(L,-1);
        lua_pop(L,1);
        emit sendgun(index);
    }
    else
    {
        emit sendgun(0);
    }
}

void Lua::getscopeinfo(QString gun)
{
    QString HOLOSIGHT=gun+QStringLiteral("_HOLOSIGHT");
    QString X8_SCOPE=gun+QStringLiteral("_X8_SCOPE");;
    QString X16_SCOPE=gun+QStringLiteral("_X16_SCOPE");;
    QString HANDMADESIGHT=gun+QStringLiteral("_HANDMADESIGHT");;
    lua_getglobal(L,HOLOSIGHT.toStdString().c_str());
    bool isHOLOSIGHT=lua_toboolean(L,-1);
    lua_pop(L,1);

    lua_getglobal(L,X8_SCOPE.toStdString().c_str());
    bool isX8_SCOPE=lua_toboolean(L,-1);
    lua_pop(L,1);

    lua_getglobal(L,X16_SCOPE.toStdString().c_str());
    bool isX16_SCOPE=lua_toboolean(L,-1);
    lua_pop(L,1);

    lua_getglobal(L,HANDMADESIGHT.toStdString().c_str());
    bool isHANDMADESIGHT=lua_toboolean(L,-1);
    lua_pop(L,1);

    if(isHOLOSIGHT)
        emit sendscope(QString("HOLOSIGHT"));
    else if(isX8_SCOPE)
        emit sendscope(QString("X8_SCOPE"));
    else if(isX16_SCOPE)
        emit sendscope(QString("X16_SCOPE"));
    else if(isHANDMADESIGHT)
        emit sendscope(QString("HANDMADESIGHT"));
    else
        emit sendscope(QStringLiteral("机瞄"));
}


void Lua::changegun(WPARAM wParam, LPARAM lParam)
{
    QString HOLOSIGHT=currentgunname+QStringLiteral("_HOLOSIGHT");
    QString X8_SCOPE=currentgunname+QStringLiteral("_X8_SCOPE");
    QString X16_SCOPE=currentgunname+QStringLiteral("_X16_SCOPE");
    QString HANDMADESIGHT=currentgunname+QStringLiteral("_HANDMADESIGHT");
    bool isopen;
    switch(reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam)->vkCode)
    {
        case 27:
            lua_getglobal(L,"kickback");
            isopen=lua_toboolean(L,-1);
            lua_pop(L,1);
            if(isopen)
            {
                lua_pushboolean(L,false);
                lua_setglobal(L,HOLOSIGHT.toStdString().c_str());
                lua_pushboolean(L,false);
                lua_setglobal(L,X8_SCOPE.toStdString().c_str());
                lua_pushboolean(L,false);
                lua_setglobal(L,X16_SCOPE.toStdString().c_str());
                lua_pushboolean(L,false);
                lua_setglobal(L,HANDMADESIGHT.toStdString().c_str());
                lua_getglobal(L,"update");
                lua_pcall(L,0,0,0);
            }
            else{
                lua_pushboolean(L,false);
                lua_setglobal(L,"kickback");
                lua_getglobal(L,"update");
                lua_pcall(L,0,0,0);
            }
            break;

        case 49:
        case 97:
            lua_pushboolean(L,true);
            lua_setglobal(L,"kickback");
            lua_pushnumber(L,1);
            lua_setglobal(L,"gun");
            break;
        case 50:
        case 98:
            lua_pushboolean(L,true);
            lua_setglobal(L,"kickback");
            lua_pushnumber(L,2);
            lua_setglobal(L,"gun");
            break;
        case 51:
        case 99:
            lua_pushboolean(L,true);
            lua_setglobal(L,"kickback");
            lua_pushnumber(L,3);
            lua_setglobal(L,"gun");
            break;
        case 52:
        case 100:
            lua_pushboolean(L,true);
            lua_setglobal(L,"kickback");
            lua_pushnumber(L,4);
            lua_setglobal(L,"gun");
            break;
        case 53:
        case 101:
            lua_pushboolean(L,true);
            lua_setglobal(L,"kickback");
            lua_pushnumber(L,5);
            lua_setglobal(L,"gun");
            break;
        case 54:
        case 102:
            lua_pushboolean(L,true);
            lua_setglobal(L,"kickback");
            lua_pushnumber(L,6);
            lua_setglobal(L,"gun");
            break;


        case 55:
        case 103:
            lua_pushboolean(L,true);
            lua_setglobal(L,HOLOSIGHT.toStdString().c_str());
            lua_pushboolean(L,false);
            lua_setglobal(L,X8_SCOPE.toStdString().c_str());
            lua_pushboolean(L,false);
            lua_setglobal(L,X16_SCOPE.toStdString().c_str());
            lua_pushboolean(L,false);
            lua_setglobal(L,HANDMADESIGHT.toStdString().c_str());
            lua_getglobal(L,"update");
            lua_pcall(L,0,0,0);
            break;
        case 56:
        case 104:
            lua_pushboolean(L,false);
            lua_setglobal(L,HOLOSIGHT.toStdString().c_str());
            lua_pushboolean(L,true);
            lua_setglobal(L,X8_SCOPE.toStdString().c_str());
            lua_pushboolean(L,false);
            lua_setglobal(L,X16_SCOPE.toStdString().c_str());
            lua_pushboolean(L,false);
            lua_setglobal(L,HANDMADESIGHT.toStdString().c_str());
            lua_getglobal(L,"update");
            lua_pcall(L,0,0,0);
            break;
        case 57:
        case 105:
            lua_pushboolean(L,false);
            lua_setglobal(L,HOLOSIGHT.toStdString().c_str());
            lua_pushboolean(L,false);
            lua_setglobal(L,X8_SCOPE.toStdString().c_str());
            lua_pushboolean(L,true);
            lua_setglobal(L,X16_SCOPE.toStdString().c_str());
            lua_pushboolean(L,false);
            lua_setglobal(L,HANDMADESIGHT.toStdString().c_str());
            lua_getglobal(L,"update");
            lua_pcall(L,0,0,0);
            break;
        case 48:
        case 96:
            lua_pushboolean(L,false);
            lua_setglobal(L,HOLOSIGHT.toStdString().c_str());
            lua_pushboolean(L,false);
            lua_setglobal(L,X8_SCOPE.toStdString().c_str());
            lua_pushboolean(L,false);
            lua_setglobal(L,X16_SCOPE.toStdString().c_str());
            lua_pushboolean(L,true);
            lua_setglobal(L,HANDMADESIGHT.toStdString().c_str());
            lua_getglobal(L,"update");
            lua_pcall(L,0,0,0);
            break;
        default:
            break;
    }
    getguninfo();
}



void Lua::run()
{
    if(luaL_loadfile(L,"main.lua"))
    {
        const char* errorMsg = lua_tostring(L, -1);
        lua_pop(L,-1);
        //qDebug()<<errorMsg;
    }
    else
    {
        timer.start();
        if(lua_pcall(L,0,0,0))
        {
            const char* errorMsg = lua_tostring(L, -1);
            lua_pop(L,-1);
            //qDebug()<<errorMsg;
        }
    }
}

Lua *&Lua::getinstance()
{
    if (instance == nullptr)
    {
        QMutexLocker locker(&instanceMutex);
        if(instance == nullptr)
            instance = new Lua();
    }
    return instance;
}

inline QElapsedTimer &Lua::gettimer()
{
    return timer;
}

Lua::~Lua()
{
    lua_close(L);//清空Lua
    L=nullptr;
}

void Lua::OnEvent(WPARAM wParam, LPARAM lParam)
{
    lua_getglobal(L,"OnEvent");
    lua_pushstring(L,"MOUSE_BUTTON_PRESSED");
    switch(wParam)
    {
    case WM_LBUTTONDOWN:
        lua_pushnumber(L,1);
        break;
    case WM_RBUTTONDOWN:
        lua_pushnumber(L,2);
        break;
    default:
        break;
    }
    lua_pcall(L,2,0,0);
}

void Lua::setcurrentgunname(QString name)
{
    currentgunname=name;
}

int IsMouseButtonPressed(lua_State* L)
{
    int mouse=lua_tonumber(L,1);
    switch(mouse)
    {
    case 1:
        lua_pushboolean(L,GetAsyncKeyState(VK_LBUTTON));
        break;
    case 3:
        lua_pushboolean(L,GetAsyncKeyState(VK_RBUTTON));
        break;
    }
    return 1;
}

int GetRunningTime(lua_State* L)
{
    lua_pushnumber(L,Lua::getinstance()->gettimer().elapsed());
    return 1;
}

int MoveMouseRelative(lua_State* L)
{
    INPUT input={0};
    input.type=INPUT_MOUSE;
    input.mi.dx=lua_tonumber(L,1);
    input.mi.dy=lua_tonumber(L,2);
    input.mi.dwFlags=MOUSEEVENTF_MOVE;
    SendInput(1,&input,sizeof(INPUT));
    return 0;
}

int IsModifierPressed(lua_State* L)
{
    const char* key=lua_tostring(L,1);
    if(key==QString("lctrl"))
    {
        lua_pushboolean(L, GetAsyncKeyState(VK_LCONTROL));
    }
    return 1;
}

int PressKey(lua_State* L)
{
    const char* key=lua_tostring(L,1);
    INPUT Input = { 0 };
    Input.type = INPUT_KEYBOARD;

    if(key==QString("pause"))
    {
        Input.ki.wVk =VK_PAUSE;
        Input.ki.dwFlags = 0;
        SendInput(1, &Input, sizeof(INPUT));
    }
    else if(key==QString("r"))
    {
        Input.ki.wVk ='R';
        Input.ki.dwFlags = 0;
        SendInput(1, &Input, sizeof(INPUT));
    }
    else if(key==QString("e"))
    {
        Input.ki.wVk ='E';
        Input.ki.dwFlags = 0;
        SendInput(1, &Input, sizeof(INPUT));
    }
    return 0;
}

int ReleaseKey(lua_State* L)
{
    const char* key=lua_tostring(L,1);
    INPUT Input = { 0 };
    Input.type = INPUT_KEYBOARD;
    if(key==QString("pause"))
    {
        Input.ki.wVk =VK_PAUSE;
        Input.ki.dwFlags = KEYEVENTF_KEYUP;
        SendInput(1, &Input, sizeof(INPUT));
    }
    else if(key==QString("r"))
    {
        Input.ki.wVk ='R';
        Input.ki.dwFlags = KEYEVENTF_KEYUP;
        SendInput(1, &Input, sizeof(INPUT));
    }
    else if(key==QString("e"))
    {
        Input.ki.wVk ='E';
        Input.ki.dwFlags = KEYEVENTF_KEYUP;
        SendInput(1, &Input, sizeof(INPUT));
    }
    return 0;
}

int GetMousePosition(lua_State* L)
{
    POINT point;
    GetCursorPos(&point);
    lua_pushnumber(L,point.x);
    lua_pushnumber(L,point.y);
    return 2;
}

int MoveMouseTo(lua_State* L)
{
    int x=lua_tonumber(L,1);
    int y=lua_tonumber(L,2);
    INPUT input = { 0 };
    input.type = INPUT_MOUSE;
    input.mi.dx = (x*(65535 / GetSystemMetrics(SM_CXSCREEN)));
    input.mi.dy = (y*(65535 / GetSystemMetrics(SM_CYSCREEN)));
    input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
     SendInput(1, &input, sizeof(INPUT));
    return 0;
}

int PressAndReleaseMouseButton(lua_State* L)
{
    const char* key=lua_tostring(L,1);
    INPUT Input = { 0 };
    Input.type = INPUT_KEYBOARD;

    if(key==QString("pause"))
    {
        Input.ki.wVk =VK_PAUSE;
        Input.ki.dwFlags = 0;
        SendInput(1, &Input, sizeof(INPUT));
        Input.ki.dwFlags = KEYEVENTF_KEYUP;
        SendInput(1, &Input, sizeof(INPUT));
    }
    else if(key==QString("r"))
    {
        Input.ki.wVk ='R';
        Input.ki.dwFlags = 0;
        SendInput(1, &Input, sizeof(INPUT));
        Input.ki.dwFlags = KEYEVENTF_KEYUP;
        SendInput(1, &Input, sizeof(INPUT));
    }
    else if(key==QString("e"))
    {
        Input.ki.wVk ='E';
        Input.ki.dwFlags = 0;
        SendInput(1, &Input, sizeof(INPUT));
        Input.ki.dwFlags = KEYEVENTF_KEYUP;
        SendInput(1, &Input, sizeof(INPUT));
    }
    return 0;
}

Lua::Deleter::Deleter(QMutex& Mutex):deleterMutex(Mutex)
{

}

Lua::Deleter::~Deleter()
{
    QMutexLocker locker(&deleterMutex);
    if(Lua::instance!=nullptr)
    {
        delete Lua::instance;
        Lua::instance=nullptr;
    }
}
